﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Data;
using System.Globalization;
using ITunesSolver.Data;
using System.IO;
using System.Diagnostics;

namespace ITunesSolver.Helpers
{
    public class TrackMatchHelper
    {
        public static CompareResult Compare(Song songA, Song songB)
        {
            CompareResult compareResult = new CompareResult();

            compareResult.CompareFlag = CompareFlag.NoResult;
            compareResult.LocationsEqual = false;
            compareResult.PathsEqual = false;
            compareResult.FileNamesEqual = false;
            compareResult.MetaDatasEqual = false;

            if (songA == null)
            {
                compareResult.LocationStringCompare = 1;
                compareResult.CompareFlag = CompareFlag.OnlyInFileB;
                return compareResult;
            }
            if (songB == null)
            {
                compareResult.LocationStringCompare = -1;
                compareResult.CompareFlag = CompareFlag.OnlyInFileA;
                return compareResult;
            }

            string locationA = songA.CleanedLocation;
            string locationB = songB.CleanedLocation;

            locationA = (locationA == null) ? string.Empty : locationA.ToLower();
            locationB = (locationB == null) ? string.Empty : locationB.ToLower();

            compareResult.CompareFlag = CompareFlag.AllDifferent;
            compareResult.LocationStringCompare = String.Compare(locationA, locationB);

            string nameA = songA.CleanedName;
            string artistA = songA.CleanedArtist;
            string albumA = songA.CleanedAlbum;
            nameA = (nameA == null) ? string.Empty : nameA.ToLower();
            artistA = (artistA == null) ? string.Empty : artistA.ToLower();
            albumA = (albumA == null) ? string.Empty : albumA.ToLower();

            string nameB = songB.CleanedName;
            string artistB = songB.CleanedArtist;
            string albumB = songB.CleanedAlbum;
            nameB = (nameB == null) ? string.Empty : nameB.ToLower();
            artistB = (artistB == null) ? string.Empty : artistB.ToLower();
            albumB = (albumB == null) ? string.Empty : albumB.ToLower();

            string fileNameA = string.Empty;
            string pathA = string.Empty;
            try
            {
                if (songA.Location != null && songA.Location != string.Empty)
                {
                    string location = songA.Location.Replace("file://localhost/", "");
                    pathA = Path.GetFullPath(location);
                    fileNameA = Path.GetFileName(songA.Location);
                }
            }
            catch(Exception ex)
            {
                throw ex;
            }

            string fileNameB = string.Empty;
            string pathB = string.Empty;
            try
            {
                if (songB.Location != null && songB.Location != string.Empty)
                {
                    string location = songB.Location.Replace("file://localhost/", "");
                    pathB = Path.GetFullPath(location);
                    fileNameB = Path.GetFileName(songB.Location);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            compareResult.FileNamesEqual = (String.Compare(fileNameA, fileNameB) == 0) && (fileNameA != string.Empty);
            compareResult.PathsEqual = (String.Compare(pathA, pathB) == 0) && (pathA != string.Empty);
            compareResult.MetaDatasEqual = (String.Compare(nameA, nameB) == 0) && (String.Compare(artistA, artistB) == 0) && (String.Compare(albumA, albumB) == 0);

            if (compareResult.LocationStringCompare == 0)
                compareResult.CompareFlag = CompareFlag.LocationsEqual;
            else if (compareResult.FileNamesEqual)
                compareResult.CompareFlag = CompareFlag.FileNamesEqual;
            else if (compareResult.PathsEqual)
                compareResult.CompareFlag = CompareFlag.PathsEqual;
            else if (compareResult.MetaDatasEqual)
                compareResult.CompareFlag = CompareFlag.MetaDataEqual;

            if (compareResult.CompareFlag == CompareFlag.AllDifferent)
            {
                if (compareResult.LocationStringCompare < 0)
                {
                    compareResult.CompareFlag = CompareFlag.OnlyInFileA;
                }
                else if (compareResult.LocationStringCompare > 0)
                {
                    compareResult.CompareFlag = CompareFlag.OnlyInFileB;
                }
            }

            return compareResult;
        }

        public static HashSet<CombinedSong> CompareTrackLibraries(ITunesLibrary iTunesLibraryA, ITunesLibrary iTunesLibraryB)
        {
            HashSet<CombinedSong> combined = new HashSet<CombinedSong>();

            CompareResult compareResult = null;
            Song[] songArrA = iTunesLibraryA.Songs.ToArray();
            Song[] songArrB = iTunesLibraryB.Songs.ToArray();

            bool finishedA = false;
            bool finishedB = false;
            int i = 0;
            int j = 0;
            int index = 0;

            while (!finishedA || !finishedB)
            {
                finishedA = (i >= songArrA.Length);
                finishedB = (j >= songArrB.Length);

                if (!finishedA && !finishedB)
                {

                    compareResult = Compare(songArrA[i], songArrB[j]);

                    switch (compareResult.CompareFlag)
                    {
                        case CompareFlag.OnlyInFileA:
                            Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " A: " + songArrA[i].CleanedLocation + " B: NULL");

                            combined.Add(new CombinedSong()
                            {
                                Index = index,
                                SongA = songArrA[i],
                                SongB = null,
                                Combined = songArrA[i],
                                CompareResult = compareResult
                            });
                            i++;
                            break;
                        case CompareFlag.OnlyInFileB:
                            Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " A: NULL " + " B: " + songArrB[j].CleanedLocation);
                            combined.Add(new CombinedSong()
                            {
                                Index = index,
                                SongA = null,
                                SongB = songArrB[j],
                                Combined = songArrB[j],
                                CompareResult = compareResult
                            });
                            j++;
                            break;
                        case CompareFlag.NoResult:
                            throw new Exception("No Result in match");
                            break;
                        case CompareFlag.MetaDataEqual:
                            Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " A: " + songArrA[i].CleanedLocation + " B: " + songArrB[j].CleanedLocation);
                            combined.Add(new CombinedSong()
                            {
                                Index = index,
                                SongA = songArrA[i],
                                SongB = songArrB[j],
                                Combined = songArrA[i],
                                CompareResult = compareResult
                            });
                            i++;
                            j++;
                            break;
                        case CompareFlag.LocationsEqual:
                            Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " A: " + songArrA[i].CleanedLocation + " B: " + songArrB[j].CleanedLocation);
                            combined.Add(new CombinedSong()
                            {
                                Index = index,
                                SongA = songArrA[i],
                                SongB = songArrB[j],
                                Combined = songArrA[i],
                                CompareResult = compareResult
                            });
                            i++;
                            j++;
                            break;
                        case CompareFlag.PathsEqual:
                        case CompareFlag.FileNamesEqual:
                        case CompareFlag.AllDifferent:
                            switch (compareResult.LocationStringCompare)
                            {
                                case -1:
                                    Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " LocationStringCompare: " + compareResult.LocationStringCompare + " A: " + songArrA[i].CleanedLocation + " B: " + songArrB[j].CleanedLocation);
                                    combined.Add(new CombinedSong()
                                    {
                                        Index = index,
                                        SongA = songArrA[i],
                                        SongB = null,
                                        Combined = songArrA[i],
                                        CompareResult = compareResult
                                    });
                                    i++;
                                    break;
                                case 1:
                                    Trace.WriteLine("res: " + compareResult.CompareFlag.ToString() + " LocationStringCompare: " + compareResult.LocationStringCompare + " A: " + songArrA[i].CleanedLocation + " B: " + songArrB[j].CleanedLocation);
                                    combined.Add(new CombinedSong()
                                    {
                                        Index = index,
                                        SongA = null,
                                        SongB = songArrB[j],
                                        Combined = songArrB[j],
                                        CompareResult = compareResult
                                    });
                                    j++;
                                    break;
                            }
                            break;
                    }
                }
                else if (!finishedA)
                {
                    //do rest of A
                    combined.Add(new CombinedSong()
                    {
                        Index = index,
                        SongA = songArrA[i],
                        SongB = null,
                        Combined = songArrA[i],
                        CompareResult = compareResult
                    });
                    i++;
                }
                else if (!finishedB)
                {
                    combined.Add(new CombinedSong()
                    {
                        Index = index,
                        SongA = null,
                        SongB = songArrB[j],
                        Combined = songArrB[j],
                        CompareResult = compareResult
                    });
                    j++;
                }

                index++;
            }

            return combined;
        }
    }
}


